package com.yanqu.road.server.manager.cookboy;

import com.yanqu.road.dao.impl.player.CrossCommonActivityDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.cookboy.process2.*;
import com.yanqu.road.entity.log.cross.LogCookBoy2AutoJoin;
import com.yanqu.road.entity.autodata.cookboy.CookBoy2AutoJoinRecord;
import com.yanqu.road.entity.autodata.cookboy.CrossCookBoy2AutoJoinSpoon;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.cross.CrossUserRank;
import com.yanqu.road.logic.bussiness.cross.CrossCookBoyBussiness;
import com.yanqu.road.logic.cross.CrossActivityRankListModel;
import com.yanqu.road.logic.pb.CrossActivityPb;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.thread.ThreadTaskManger;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.cookboy.CookBoyProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.pb.union.UnionActivityGroupProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.relation.CrossRelationRankMgr;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.pb.cookboy.CrossCookBoyPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.util.ConcurrentHashSet;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossCookBoy2 {

    private Logger logger = LogManager.getLogger(CrossCookBoy2.class.getName());

    private ActivityInfo activityInfo;

    private Map<Long, CookBoyUpUser> cookerMap = new ConcurrentHashMap<>();

    private List<CookBoyUpUser> needSyncUserList = new ArrayList<>();
    private List<CookBoyUpUser> needInsertUserList = new ArrayList<>();
    private List<CookBoyUpUser> needUpdateUserList = new ArrayList<>();

    //index
    private List<HorseRaceLamp> needHorseRaceLampList = new ArrayList<>();//同步跑马灯

    //用户id场次no
    private Map<Long,Map<Integer, CookBoy2DishTable>> cookBoyTableMap = new ConcurrentHashMap<>();

    //正在开还没结束的桌子
    private Map<Long,Map<Integer, CookBoy2DishTable>> openCookBoyTableMap = new ConcurrentHashMap<>();

    private List<CookBoy2DishTable> needInsertTableList = new ArrayList<>();
    private List<CookBoy2DishTable> needUpdateTableList = new ArrayList<>();



    //用户的互宴信息
    private List<CookBoy2UserJoinData> joinList = new ArrayList<>();

    //大的userId
    private Map<Long,CookBoy2UserJoinData> joinMap = new ConcurrentHashMap<>();

    private List<CookBoy2UserJoinData> joinInsertList = new ArrayList<>();
    private List<CookBoy2UserJoinData> joinUpdateList = new ArrayList<>();

    //待同步的区服
    private Set<Long> syncServerIdList;

    // 自动回访线程池
    private ThreadTaskManger autoJoinThreadPool;

    private Map<Long, CrossCookBoy2AutoJoinSpoon> autoJoinSpoonMap = new HashMap<>(); // 自动回访汤勺
    private final Map<Long, Map<Long, CookBoy2AutoJoinRecord>> autoJoinRecordMap = new HashMap<>(); // 自动回访记录 访客Id -> 摊主Id -> 访问记录

    public int getActivityId(){
        return activityInfo.getActivityId();
    }

    public ActivityInfo getActivityInfo(){
        return activityInfo;
    }

    public boolean activityInWindUpTime() {
        if(null == activityInfo){
            return false;
        }
        long nowTime = System.currentTimeMillis() / 1000;
        return nowTime >= activityInfo.getEndTime() + 5 * 60 && nowTime < activityInfo.getEndShowTime();
    }

    //活动结束结算下发晋级人员
    public void activityEndWindUp(){
        if(activityInWindUpTime()){
            //活动结束了移除数据
            cookBoyTableMap = new ConcurrentHashMap<>();
            joinMap = new ConcurrentHashMap<>();
//            logger.error("清除阶段2结束数据");
//            logger.error("清除阶段2"+activityInfo.getActivityId()+"joinList清理前大小"+joinList.size());
            List<CookBoy2UserJoinData> tempRemoveList = new ArrayList<>();
            for(CookBoy2UserJoinData cookBoy2UserJoinData : joinList){
                if(cookBoy2UserJoinData != null && cookBoy2UserJoinData.getActivityId() == getActivityId()){
                    tempRemoveList.add(cookBoy2UserJoinData);
                }
            }
            for(CookBoy2UserJoinData a : tempRemoveList){
                joinList.remove(a);
            }
//            logger.error("清除阶段2"+activityInfo.getActivityId()+"joinList清理后大小"+joinList.size());
            //rank userId
            Map<Integer,Long> goodBoyMap = new ConcurrentHashMap<>();
            //同步给本服
            Map<Long,List<Long>> goodBoyServerSyncMap = new ConcurrentHashMap<>();
            int minRank = CrossCookBoyActivityMgr.getCook2ToCook3Rank(getActivityId());
            CrossActivityRankListModel rankListModel = CrossRelationRankMgr.getCrossActivityRankListModel(getActivityId());
            if(rankListModel == null){
                //启动的时候可能还没全部启动完定时器已经开始跑了，排行榜还没加载完。。。。
                return;
            }
            LinkedList<CrossUserRank> rankList = rankListModel.getRankList();
            int rank = 1;
            for(CrossUserRank userRank : rankList){
                if(rank <= minRank){
//                    logger.error("阶段2晋级阶段3下发数据，配置文件晋级的排名要求"+rank+",晋级的玩家id:"+userRank.getUserId()+",玩家排名"+rank+",userRank排名:"+userRank.getRank());
                    goodBoyMap.put(userRank.getRank(),userRank.getUserId());
                    if(!goodBoyServerSyncMap.containsKey(userRank.getUserBaseInfo().getServerId())){
                        goodBoyServerSyncMap.put(userRank.getUserBaseInfo().getServerId(),new ArrayList<>());
                    }
                    goodBoyServerSyncMap.get(userRank.getUserBaseInfo().getServerId()).add(userRank.getUserId());
                }
                rank++;
            }
//            int activityId = CrossCookBoyMgr.windUpCookBoy2User(getActivityId(),goodBoyMap);
            windUpCookBoy1UserSyncServer(goodBoyServerSyncMap);
        }
    }

    public void windUpCookBoy1UserSyncServer(Map<Long,List<Long>> goodBoyServerSyncMap){
        for(Long serverId : goodBoyServerSyncMap.keySet()){
            CookBoyProto.CrossCookBoyWindUpMsg.Builder respMsg =
                    CrossCookBoyPb.parseCrossCookBoyWindUpMsg(activityInfo.getActivityId(),goodBoyServerSyncMap.get(serverId));
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_TO_COOK_BOY3, respMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    public void addCookBoy2Horse(long serverId, long userId, int dishId, long time) {
        synchronized (needHorseRaceLampList){
            HorseRaceLamp horseRaceLamp = new HorseRaceLamp();
            horseRaceLamp.setServerId(serverId);
            horseRaceLamp.setUserId(userId);
            horseRaceLamp.setDishId(dishId);
            horseRaceLamp.setTime(time);
            needHorseRaceLampList.add(horseRaceLamp);
        }
        CookBoyProto.CookBoy2horseRaceLampSyncMsg.Builder userHorseMsg = CookBoyProto.CookBoy2horseRaceLampSyncMsg.newBuilder();
        CookBoyProto.CookBoy2horseRaceLampTempMsg.Builder tempMsg = CookBoyProto.CookBoy2horseRaceLampTempMsg.newBuilder();
        tempMsg.setUserId(userId);
        tempMsg.setDishId(dishId);
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(userBaseInfo == null){
            return;
        }
        tempMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        userHorseMsg.addNoticeList(tempMsg);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_COOK_BOY2_HORSE_NOTICE_SYNC, userHorseMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void syncHorseNotice(){
        List<HorseRaceLamp> snycList = new ArrayList<>();
        synchronized (needHorseRaceLampList) {
            snycList = new ArrayList<>(needHorseRaceLampList);
            needHorseRaceLampList.clear();
        }
        if(snycList.size() > 0){
            CookBoyProto.CrossCookBoy2HorseSyncServerMsg.Builder respMsg =
                    CrossCookBoyPb.parseCookBoy2HorseSyncServerMsg(snycList,getActivityId());
            if(respMsg != null){
                for(long serverId : activityInfo.getServerIdList2()){
                    YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_HORSE_NOTICE_SYNC, respMsg);
                    MessageHelper.sendPacket(serverId, 0, pbMsg);
                }
            }
        }
    }

    private void removeOpenTable(CookBoy2DishTable cookBoy2DishTable){
        if(openCookBoyTableMap.containsKey(cookBoy2DishTable.getUserId())){
            openCookBoyTableMap.get(cookBoy2DishTable.getUserId()).remove(cookBoy2DishTable.getNo());
        }
    }

    private void addOpenTable(CookBoy2DishTable cookBoy2DishTable){
        if(!openCookBoyTableMap.containsKey(cookBoy2DishTable.getUserId())){
            openCookBoyTableMap.put(cookBoy2DishTable.getUserId(),new ConcurrentHashMap<>());
        }
        openCookBoyTableMap.get(cookBoy2DishTable.getUserId()).put(cookBoy2DishTable.getNo(),cookBoy2DishTable);
    }

    private Map<CookBoy2DishTable, YanQuMessage> endTableMsgMap = new ConcurrentHashMap<>();

    private CookBoy2TableReward endTable(CookBoy2DishTable cookBoy2DishTable){
        CookBoy2TableReward res = null;
        if(cookBoy2DishTable.getOverTime() == 0){
            res = new CookBoy2TableReward();
            cookBoy2DishTable.setOverTime(System.currentTimeMillis());
            removeOpenTable(cookBoy2DishTable);
            res.setActivityId(getActivityId());
            res.setUserId(cookBoy2DishTable.getUserId());
            //结束了加上没坐完的自动填充机器人那部分积分
            CookBoy2Spoon cookboy2Spoon = CrossCookBoyActivityMgr.getCookBoy2MinSpoon(getActivityId());
            CookBoy2DishConfig cookBoy2DishConfig = CrossCookBoyActivityMgr.getDishCondfig(getActivityId(),cookBoy2DishTable.getDishId());
            int needAddNum = cookBoy2DishConfig.getSeat() - cookBoy2DishTable.getCookBoy2JoinerMap().size();


            long addIntegral = 0;
            if(needAddNum > 0){
                Map<Long, CookBoy2Joiner> joinerMap = cookBoy2DishTable.getCookBoy2JoinerMap();
                for(int i = 0;i < needAddNum;i++){
                    int robotId = CrossCookBoyActivityMgr.getRandomCookBoy2Robot(getActivityId());
                    CookBoy2Joiner cookBoy2Joiner = new CookBoy2Joiner();
                    cookBoy2Joiner.setServerId(0);
                    cookBoy2Joiner.setUserId(joinerMap.size() + 1);
                    cookBoy2Joiner.setGifttId(cookboy2Spoon.getItemId());
                    cookBoy2Joiner.setPos(joinerMap.size() + 1);
                    cookBoy2Joiner.setRobotId(robotId);
                    joinerMap.put(cookBoy2Joiner.getUserId(),cookBoy2Joiner);
                }
                cookBoy2DishTable.setCookBoy2JoinerMap(joinerMap);
                addIntegral  = cookboy2Spoon.getUserIntegral() * needAddNum * CrossCookBoyActivityMgr.getCookBoy2RobotAdd(getActivityId()) / 1000;
                cookBoy2DishTable.setIntegral(cookBoy2DishTable.getIntegral() + addIntegral);
                res.setIntegral(addIntegral);
            }
            //同步结束了
            addToEndTableMsg(cookBoy2DishTable, addIntegral);
//            MessageHelper.sendChannelPacket(cookBoy2DishTable.getServerId(), cookBoy2DishTable.getUserId(), pbOpenerMsg);
            synchronized (needUpdateTableList){
                if(!needUpdateTableList.contains(cookBoy2DishTable)){
                    needUpdateTableList.add(cookBoy2DishTable);
                }
            }
            synchronized (needSyncUserList){
                if (!needSyncUserList.contains(cookerMap.get(cookBoy2DishTable.getUserId()))) {
                    needSyncUserList.add(cookerMap.get(cookBoy2DishTable.getUserId()));
                }
            }
        }
        return res;
    }

    private void addToEndTableMsg(CookBoy2DishTable cookBoy2DishTable, long addIntegral) {
        CookBoyProto.CrossCookBoy2RobotJoinBanquetMsg.Builder msg = CookBoyProto.CrossCookBoy2RobotJoinBanquetMsg.newBuilder();
        msg.setRet(0);
        msg.setIntegral(addIntegral);
        msg.setActivityId(getActivityId());
        msg.setHomeUserId(cookBoy2DishTable.getUserId());
        msg.setDishId(cookBoy2DishTable.getDishId());
        msg.setTableId(cookBoy2DishTable.getNo());
        msg.setUserDishId(cookBoy2DishTable.getUserDishId());
        msg.setAllIntegral(cookBoy2DishTable.getIntegral());
        YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_ROBOT_JOIN, msg);
        synchronized (endTableMsgMap) {
            endTableMsgMap.put(cookBoy2DishTable,pbOpenerMsg);
        }
    }

    public void tableCheck(){
        for(long userId : cookBoyTableMap.keySet()){
            List<CookBoy2DishTable> needSyncTableList = new ArrayList<>();
            long addIntegral = 0;
            Map<Integer,CookBoy2DishTable> userMap = cookBoyTableMap.get(userId);
            for(CookBoy2DishTable cookBoy2DishTable : new ArrayList<>(userMap.values())){
                if(cookBoy2DishTable.getOverTime() != 0)continue;
                CookBoy2TableReward eatTableRes = null;
                CookBoy2DishConfig cookBoy2DishConfig = CrossCookBoyActivityMgr.getDishCondfig(getActivityId(),cookBoy2DishTable.getDishId());
                if(cookBoy2DishConfig == null){
                    logger.error("小当家2找不到配置的菜品id"+cookBoy2DishTable.getDishId());
                    continue;
                }
                //时间到了结束//座位坐满了结束//每天到了晚上22点也结束
                if(System.currentTimeMillis() - cookBoy2DishTable.getOpenTime() > CrossCookBoyActivityMgr.getServeDishTableTime(getActivityId()) * 60 * 1000 ||
                        cookBoy2DishTable.getCookBoy2JoinerMap().size() >= cookBoy2DishConfig.getSeat() ||
                        !CrossCookBoyActivityMgr.isActivityMatchTime(activityInfo)){
                    synchronized (cookBoy2DishTable) {
                        eatTableRes = endTable(cookBoy2DishTable);
                    }
                }
                if(eatTableRes != null){
                    needSyncTableList.add(cookBoy2DishTable);
                    addIntegral = addIntegral + eatTableRes.getIntegral();
                }
            }
            if(needSyncTableList.size() > 0){
                //把机器人的积分也同步下去，不然客户端刷新不准，会等通知积分通知本服，本服触发condition，再到跨服排行，才有他的积分
                syncTableServers(userId,needSyncTableList,addIntegral);
                synchronized (endTableMsgMap) {
                    for (CookBoy2DishTable cookBoy2DishTable :endTableMsgMap.keySet()){
                        MessageHelper.sendPacket(cookBoy2DishTable.getServerId(), cookBoy2DishTable.getUserId(), endTableMsgMap.get(cookBoy2DishTable));
                    }
                    endTableMsgMap.clear();
                }
                synchronized (needSyncUserList){
                    if(!needSyncUserList.contains(cookerMap.get(userId))){
                        needSyncUserList.add(cookerMap.get(userId));
                    }
                }
            }else {
                synchronized (endTableMsgMap) {
                    for (CookBoy2DishTable cookBoy2DishTable :endTableMsgMap.keySet()){
                        MessageHelper.sendPacket(cookBoy2DishTable.getServerId(), cookBoy2DishTable.getUserId(), endTableMsgMap.get(cookBoy2DishTable));
                    }
                    endTableMsgMap.clear();
                }
            }
        }
//        syncCookerServer();
    }

    //addIntegral把参加的人的积分加上去，要同步这个玩家的积分变化，不然要等到本服加上后同步到跨服排行榜,机器人的也没加，不管了
    public void syncTableServer(CookBoy2DishTable cookBoy2DishTable,long addIntegral){
        for(long serverId : activityInfo.getServerIdList2()){
            int dishNum = 0;
            if(cookBoyTableMap.containsKey(cookBoy2DishTable.getUserId())){
                dishNum = cookBoyTableMap.get(cookBoy2DishTable.getUserId()).size();
            }
            Map<Integer,CookBoy2DishTable> tableMap = new ConcurrentHashMap<>();
            tableMap.put(cookBoy2DishTable.getNo(),cookBoy2DishTable);
            CookBoyProto.CrossCookBoy2TableSyncMsg.Builder respMsg =
                    CrossCookBoyPb.parseCrossCookBoy2TableSyncMsg(tableMap,getActivityId(),cookBoy2DishTable.getServerId(),cookBoy2DishTable.getUserId(),dishNum,addIntegral);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_TABLE_SYNC, respMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    public void syncTableServers(long userId, List<CookBoy2DishTable> cookBoy2DishTableList,long addIntegral){
        if(cookBoy2DishTableList.size() == 0){
            return;
        }
        for(long serverId : activityInfo.getServerIdList2()){
            int dishNum = 0;
            if(cookBoyTableMap.containsKey(userId)){
                dishNum = cookBoyTableMap.get(userId).size();
            }
            Map<Integer,CookBoy2DishTable> tableMap = new ConcurrentHashMap<>();
            for(CookBoy2DishTable cookBoy2DishTable : cookBoy2DishTableList){
                tableMap.put(cookBoy2DishTable.getNo(),cookBoy2DishTable);
            }
            CookBoyProto.CrossCookBoy2TableSyncMsg.Builder respMsg =
                    CrossCookBoyPb.parseCrossCookBoy2TableSyncMsg(tableMap,getActivityId(),cookerMap.get(userId).getServerId(),userId,dishNum,addIntegral);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_TABLE_SYNC, respMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    //获取这个人不能试吃的人
    private List<Long> getCookerNoEatUserIdList(long cookerId){
        Map<Long,Integer> eatCountMap = new ConcurrentHashMap<>();
        List<Long> noEatUserIdList = new ArrayList<>();
        if(!openCookBoyTableMap.containsKey(cookerId) || openCookBoyTableMap.get(cookerId).size() == 0){
            return null;
        }
        Map<Integer, CookBoy2DishTable> openTableMap = openCookBoyTableMap.get(cookerId);
        for(CookBoy2DishTable table : openTableMap.values()){
            Map<Long, CookBoy2Joiner> joinerMap = table.getCookBoy2JoinerMap();
            for(CookBoy2Joiner joiner : joinerMap.values()){
                if(eatCountMap.containsKey(joiner.getUserId())){
                    eatCountMap.put(joiner.getUserId(),eatCountMap.get(joiner.getUserId()) + 1);
                }else{
                    eatCountMap.put(joiner.getUserId(),1);
                }
            }
        }
        for(Long userId : eatCountMap.keySet()){
            if(eatCountMap.get(userId) == openTableMap.size()){
                noEatUserIdList.add(userId);
            }
        }
        return noEatUserIdList;
    }

    //给桌子排下名
    private void cookerRanking(){
        for(CookBoyUpUser cookBoyUpUser : cookerMap.values()){
            if(!cookBoyTableMap.containsKey(cookBoyUpUser.getUserId())){
                cookBoyUpUser.setIntegral(0);
                cookBoyUpUser.setRank(0);
            }else{
                Map<Integer, CookBoy2DishTable> cookBoy2DishTableMap = cookBoyTableMap.get(cookBoyUpUser.getUserId());
                long integral = 0;
                for(CookBoy2DishTable cookBoy2DishTable : cookBoy2DishTableMap.values()){
                    integral += cookBoy2DishTable.getIntegral();
                }
                cookBoyUpUser.setIntegral(integral);
            }
        }
        List<CookBoyUpUser> cookerList = new ArrayList<>(cookerMap.values());
        cookerList.sort(new CookerSort());
        int rank = 1;
        for(CookBoyUpUser cookBoyUpUser : cookerList){
            cookBoyUpUser.setRank(rank);
            rank++;
        }
    }

    public void setActivityInfo(ActivityInfo activityInfo){
        repair();
        this.activityInfo = activityInfo;
    }

    public void checkDishStatus(long serverId, List<CookBoyProto.NeedCheckCookBoy2DishMsg> dishList) {
        for (CookBoyProto.NeedCheckCookBoy2DishMsg dishMsg : dishList) {
            long userId = dishMsg.getUserId();
            int dishId = dishMsg.getDishId();
            Map<Integer, CookBoy2DishTable> tableMap = cookBoyTableMap.get(userId);
            if (tableMap == null) {
                continue;
            }
            CookBoy2DishTable dishTable = tableMap.get(dishId);
            if (dishTable == null) {
                continue;
            }
            if (dishTable.getOverTime() == 0 || System.currentTimeMillis() - dishTable.getOverTime() < 30*1000L) {
                continue;
            }
            int needAddNum = 0;
            for (CookBoy2Joiner joiner : new ArrayList<>(dishTable.getCookBoy2JoinerMap().values())) {
                if (joiner.getRobotId() != 0) {
                    needAddNum++;
                }
            }
            long addIntegral = 0;
            if (needAddNum > 0) {
                CookBoy2Spoon cookboy2Spoon = CrossCookBoyActivityMgr.getCookBoy2MinSpoon(getActivityId());
                addIntegral  = cookboy2Spoon.getUserIntegral() * needAddNum * CrossCookBoyActivityMgr.getCookBoy2RobotAdd(getActivityId()) / 1000;
            }
            addToEndTableMsg(dishTable,addIntegral);
        }
    }

    public void syncActivityBack(long serverId) {
        syncServerIdList.remove(serverId);
    }

    public void setSyncServerIdList(Set<Long> syncServerIdList) {
        this.syncServerIdList = syncServerIdList;
    }

    //从大到小
    static class CookerSort implements Comparator<CookBoyUpUser> {
        @Override
        public int compare(CookBoyUpUser o1, CookBoyUpUser o2) {
            if (o1.getIntegral() == o2.getIntegral()) {
                return 0;
            }
            if (o1.getIntegral() <= o2.getIntegral()) {
                return 1;
            }
            return -1;
        }
    }

    //同步每一个参赛者可吃可不吃状态
    public void syncCookerServer(){
//        logger.error("同步数据数目"+needSyncUserList.size());
        List<CookBoyUpUser> tempList;
        synchronized (needSyncUserList) {
            tempList = new ArrayList<>(needSyncUserList);
            needSyncUserList.clear();
        }
        if (tempList.isEmpty()) {
            return;
        }
        CookBoyProto.CrossCookBoy2CookerSyncMsg.Builder respMsg = CookBoyProto.CrossCookBoy2CookerSyncMsg.newBuilder();
        respMsg.setActivityId(getActivityId());
        for(CookBoyUpUser cookBoyUpUser : tempList){
            CookBoyProto.CrossCookBoy2CookerTempMsg.Builder userMsg = CookBoyProto.CrossCookBoy2CookerTempMsg.newBuilder();
            userMsg.setServerId(cookBoyUpUser.getServerId());
            userMsg.setUserId(cookBoyUpUser.getUserId());
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(cookBoyUpUser.getUserId());
            if(userBaseInfo == null){
                continue;
            }
            userMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            List<Long> noEatUserIdList = getCookerNoEatUserIdList(cookBoyUpUser.getUserId());
            if(noEatUserIdList == null){
                userMsg.setCanEat(false);
            }else{
                userMsg.setCanEat(true);
                userMsg.addAllNoEatUserId(noEatUserIdList);
            }
            userMsg.setRank(cookBoyUpUser.getRank());
            respMsg.addCookerList(userMsg);
        }
        for(long serverId : activityInfo.getServerIdList2()){
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_COOKER_SYNC, respMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    private CookBoy2DishTable initCookBoy2DishTable(long serverId,long userId,int id,int dishId,int no){
        CookBoy2DishTable newOne = new CookBoy2DishTable();
        newOne.setActivityId(activityInfo.getActivityId());
        newOne.setServerId(serverId);
        newOne.setUserId(userId);
        newOne.setUserDishId(id);
        newOne.setDishId(dishId);
        newOne.setOpenTime(System.currentTimeMillis());
        newOne.setOverTime(0);
        newOne.setIntegral(0);
        newOne.setJoinerData("{}");
        newOne.setNo(no);

        return newOne;
    }

    public List<Integer> getUserForbiddenSpoonIdList(long userId){
        CookBoyUpUser cookData = cookerMap.get(userId);
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if(cookData != null){
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
        }
        return forbidSpoonIdList;
    }

    public int joinTable(long serverId,long joinUserId,long homeUserId,int tableId,int spoonId,int trueActivityId, PlayerProto.PlayerBaseTempMsg joinUserInfo){
        if(!cookBoyTableMap.containsKey(homeUserId)){
            return GameErrorCode.E_COOK_BOY2_TABLE_NOT_FOUND;
        }
        Map<Integer,CookBoy2DishTable> cookBoy2DishTableMap = cookBoyTableMap.get(homeUserId);
        if(!cookBoy2DishTableMap.containsKey(tableId)){
            return GameErrorCode.E_COOK_BOY2_TABLE_NOT_FOUND;
        }
        CookBoy2Spoon cookBoy2Spoon = CrossCookBoyActivityMgr.getCookBoy2Spoon(getActivityId(),spoonId);
        if(cookBoy2Spoon == null){
            return GameErrorCode.E_COOK_BOY2_SPOON_NOT_FOUND;
        }
        CookBoy2DishTable cookBoy2DishTable = cookBoy2DishTableMap.get(tableId);

        CookBoy2DishConfig cookBoy2DishConfig = CrossCookBoyActivityMgr.getDishCondfig(getActivityId(),cookBoy2DishTable.getDishId());
        if(cookBoy2DishConfig == null){
            return GameErrorCode.E_COOK_BOY2_DISH_CONFIG_NOT_FOUND;
        }
        CookBoyUpUser cookData = cookerMap.get(homeUserId);
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if(cookData != null){
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
            if(forbidSpoonIdList.contains(spoonId)){
                return GameErrorCode.E_COOK_BOY2_EAT_SPOON_FORBID;
            }
        }

        synchronized (cookBoy2DishTable) {
            if(cookBoy2DishTable.getOverTime() != 0){
                return GameErrorCode.E_COOK_BOY2_TABLE_OVER;
            }
            if(cookBoy2DishTable.getCookBoy2JoinerMap().size() >= cookBoy2DishConfig.getSeat()){
                return GameErrorCode.E_COOK_BOY2_TABLE_SEAT_FULL;
            }
            if(!CrossCookBoyActivityMgr.isActivityMatchTime(activityInfo)){
                return GameErrorCode.E_COOK_BOY2_ACTIVITY_NOT_RUNNING;
            }
            Map<Long, CookBoy2Joiner> joinerMap = cookBoy2DishTable.getCookBoy2JoinerMap();
            if(joinerMap.containsKey(joinUserId)){
                return GameErrorCode.E_COOK_BOY2_TABLE_IS_JOIN;
            }
            CookBoy2Joiner cookBoy2Joiner = new CookBoy2Joiner();
            cookBoy2Joiner.setServerId(serverId);
            cookBoy2Joiner.setUserId(joinUserId);
            cookBoy2Joiner.setGifttId(spoonId);
            cookBoy2Joiner.setPos(joinerMap.size() + 1);
            joinerMap.put(cookBoy2Joiner.getUserId(),cookBoy2Joiner);
            cookBoy2DishTable.setCookBoy2JoinerMap(joinerMap);
            cookBoy2DishTable.setIntegral(cookBoy2DishTable.getIntegral() + cookBoy2Spoon.getUserIntegral());
        }

        CookBoyProto.CrossCookBoy2JoinTableMsg.Builder joinMsg = CookBoyProto.CrossCookBoy2JoinTableMsg.newBuilder();
        joinMsg.setRet(0);
        joinMsg.setActivityId(getActivityId());
        joinMsg.setJoinerUserId(joinUserId);
        joinMsg.setHomeUserId(homeUserId);
        joinMsg.setTableId(tableId);
        joinMsg.setSpoonId(spoonId);
        joinMsg.addAllForbidSpoonId(forbidSpoonIdList);
        if(trueActivityId > 0){
            joinMsg.setActivityId(trueActivityId);
            joinMsg.setOtherActivityId(getActivityId());
        }
        YanQuMessage pbJoinerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_JOIN_JOINER, joinMsg);

        CookBoyProto.CrossCookBoy2JoinTableMsg.Builder msg = CookBoyProto.CrossCookBoy2JoinTableMsg.newBuilder();
        msg.setRet(0);
        msg.setActivityId(getActivityId());
        msg.setJoinerUserId(joinUserId);
        msg.setHomeUserId(homeUserId);
        msg.setTableId(tableId);
        msg.setSpoonId(spoonId);
        msg.addAllForbidSpoonId(forbidSpoonIdList);
        YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_JOIN_OPENER, msg);
        MessageHelper.sendPacket(serverId, joinUserId, pbJoinerMsg);
        MessageHelper.sendPacket(cookBoy2DishTable.getServerId(), homeUserId, pbOpenerMsg);
        newJoin(homeUserId,joinUserId, trueActivityId);
        //自己加入自己
        if(joinUserId == homeUserId){
            syncTableServer(cookBoy2DishTable,cookBoy2Spoon.getUserIntegral() + cookBoy2Spoon.getJoinerIntegral());
        }else{
            syncTableServer(cookBoy2DishTable,cookBoy2Spoon.getUserIntegral());
        }
        tableCheck();
        synchronized (needUpdateTableList){
            if (!needUpdateTableList.contains(cookBoy2DishTable)) {
                needUpdateTableList.add(cookBoy2DishTable);
            }
        }
        synchronized (needSyncUserList){
            if (!needSyncUserList.contains(cookerMap.get(homeUserId))) {
                needSyncUserList.add(cookerMap.get(homeUserId));
            }
        }

        if (joinUserInfo != null) {
            UserBaseInfo userBaseInfo = PlayerBasePb.parseBaseUserInfo(joinUserInfo);
            CrossUserMgr.updateUserBaseInfo(joinUserId, userBaseInfo);
        }

        if (joinUserId != homeUserId) { // 不能回访自己，自动回访中摊主和访客的身份互换
            long hostServerId = CrossUserMgr.getServerIdByUserId(homeUserId);
            if (hostServerId != 0) {
                CookBoyProto.CrossCookBoy2AutoJoinInfoMsg.Builder req = CookBoyProto.CrossCookBoy2AutoJoinInfoMsg.newBuilder();
                req.setHostActivityId(trueActivityId);
                req.setGuestActivityId(getActivityId());
                req.setHostId(joinUserId);
                req.setGuestId(homeUserId);
                req.setSpoonId(spoonId);
                req.setHostServerId(serverId);
                UserBaseInfo guestInfo = CrossUserMgr.getUserBaseInfo(homeUserId);
                if (guestInfo != null) {
                    req.setGuestInfo(PlayerBasePb.parsePlayerBaseTempMsg(guestInfo));
                }
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_AUTO_JOIN, req);
                MessageHelper.sendPacket(hostServerId, homeUserId, pbMsg);
            }
        }

        return 0;
    }

    public void newJoin(long homeUserId, long joinUserId, int trueActivityId){
        /*if(homeUserId == joinUserId)return;
        synchronized (joinMap){
            long userId1,userId2;
            if(homeUserId > joinUserId){
                userId1 = homeUserId;
                userId2 = joinUserId;
            }else{
                userId1 = joinUserId;
                userId2 = homeUserId;
            }
            if(!joinMap.containsKey(userId1)){
                CookBoy2UserJoinData newOne = new CookBoy2UserJoinData();
                newOne.setActivityId(getActivityId());
                newOne.setUserId1(userId1);
                newOne.setUserId2(userId2);
                newOne.setJoinTime1(userId1==joinUserId?1:0);
                newOne.setJoinTime2(userId2==joinUserId?1:0);
                newOne.setLastJoinTime(System.currentTimeMillis());
                joinList.add(newOne);
                joinMap.put(userId1,newOne);
                joinInsertList.add(newOne);
            }else{
                CookBoy2UserJoinData temp = joinMap.get(userId1);
                temp.setJoinTime1(temp.getJoinTime1()+(userId1==joinUserId?1:0));
                temp.setJoinTime2(temp.getJoinTime2()+(userId2==joinUserId?1:0));
                temp.setLastJoinTime(System.currentTimeMillis());
                if(!joinUpdateList.contains(temp)){
                    joinUpdateList.add(temp);
                }
            }
        }*/
        long userId1,userId2;
        if(homeUserId > joinUserId){
            userId1 = homeUserId;
            userId2 = joinUserId;
        }else{
            userId1 = joinUserId;
            userId2 = homeUserId;
        }
        boolean isFind = false;
        for(CookBoy2UserJoinData cookBoy2UserJoinData : joinList){
            if(cookBoy2UserJoinData.getActivityId() == getActivityId() && cookBoy2UserJoinData.getUserId1() == userId1 && cookBoy2UserJoinData.getUserId2() == userId2){
                cookBoy2UserJoinData.setJoinTime1(cookBoy2UserJoinData.getJoinTime1()+(userId1==joinUserId?1:0));
                cookBoy2UserJoinData.setJoinTime2(cookBoy2UserJoinData.getJoinTime2()+(userId2==joinUserId?1:0));
                cookBoy2UserJoinData.setLastJoinTime(System.currentTimeMillis());
                synchronized (joinUpdateList){
                    if(!joinUpdateList.contains(cookBoy2UserJoinData)){
                        joinUpdateList.add(cookBoy2UserJoinData);
                    }
                }
                isFind = true;
                break;
            }
        }
        if(!isFind){
            CookBoy2UserJoinData newOne = new CookBoy2UserJoinData();
            newOne.setActivityId(getActivityId());
            newOne.setUserId1(userId1);
            newOne.setUserId2(userId2);
            newOne.setJoinTime1(userId1==joinUserId?1:0);
            newOne.setJoinTime2(userId2==joinUserId?1:0);
            newOne.setLastJoinTime(System.currentTimeMillis());
            newOne.setOtherActivityId(trueActivityId);
            synchronized (joinList){
                joinList.add(newOne);
            }
            synchronized (joinInsertList){
                joinInsertList.add(newOne);
            }
        }

    }

    private int getTableCount(){
        int count = 0;
        for(Map<Integer, CookBoy2DishTable> userMap : cookBoyTableMap.values()){
            count += userMap.size();
        }
        return count;
    }

    //是否已经上过了
    private boolean isDishEat(long userId,int userDishId){
        Map<Integer, CookBoy2DishTable> userTableMap = cookBoyTableMap.get(userId);
        for(CookBoy2DishTable cookBoy2DishTable : userTableMap.values()){
            if(cookBoy2DishTable.getUserDishId() == userDishId){
                return true;
            }
        }
        return false;
    }

    public void serveDish(long serverId,long userId,Map<Integer,Integer> dishMap){
        tableCheck();
        CookBoyProto.CookBoy2OpenTableRespMsg.Builder msg = CookBoyProto.CookBoy2OpenTableRespMsg.newBuilder();
        msg.setActivityId(getActivityId());
        int ret = 0;
        if(!cookBoyTableMap.containsKey(userId)){
            cookBoyTableMap.put(userId,new ConcurrentHashMap<>());
        }
        Map<Integer, CookBoy2DishTable> userTableMap = cookBoyTableMap.get(userId);
        if(getUserOpenDishTables(userId).size() + dishMap.size() > CrossCookBoyActivityMgr.getCookBoy2OpenTableLimit(activityInfo.getActivityId())){
            ret = GameErrorCode.E_COOK_BOY2_DISH_OPEN_LIMIT;
        }
        for(int userDishId : dishMap.keySet()){
            if(isDishEat(userId,userDishId)){
                ret = GameErrorCode.E_COOK_BOY2_DISH_IS_SERVE;
                break;
            }
        }
        if(ret != 0){
            msg.setRet(ret);
            //上了那些菜给他改回来状态
            for(int userDishId : dishMap.keySet()) {
                CookBoyProto.CrossCookBoy2FoodTableIdMsg.Builder foodTableMsg = CookBoyProto.CrossCookBoy2FoodTableIdMsg.newBuilder();
                foodTableMsg.setUserDishId(userDishId);
                foodTableMsg.setTableId(0);
                msg.addFoodList(foodTableMsg);
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_SERVE_DISH, msg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        List<CookBoy2DishTable> syncList = new ArrayList<>();
        for(int userDishId : dishMap.keySet()){
            CookBoy2DishTable newOne = initCookBoy2DishTable(serverId,userId,userDishId,dishMap.get(userDishId), getTableCount() + 1);
            cookBoyTableMap.get(userId).put(newOne.getNo(),newOne);
            addOpenTable(newOne);
            synchronized (needInsertTableList){
                if(!needInsertTableList.contains(newOne)){
                    needInsertTableList.add(newOne);
                }
            }
            syncList.add(newOne);
            CookBoyProto.CrossCookBoy2FoodTableIdMsg.Builder foodTableMsg = CookBoyProto.CrossCookBoy2FoodTableIdMsg.newBuilder();
            foodTableMsg.setUserDishId(userDishId);
            foodTableMsg.setTableId(newOne.getNo());
            msg.addFoodList(foodTableMsg);
        }
        synchronized (needSyncUserList){
            if (!needSyncUserList.contains(cookerMap.get(userId))) {
                needSyncUserList.add(cookerMap.get(userId));
            }
        }
        //同步所有区服有人开了
        syncTableServers(userId,syncList,0);
        //开宴立即同步一次
        syncCookerServer();

        msg.setRet(ret);
        /*CookBoyProto.CookBoy2UserIdTableRespMsg.Builder tableMsg = getTablesMsg(serverId,userId,0,0);
        msg.setSelfTable(tableMsg);*/
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_SERVE_DISH, msg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //获取用户开的宴会上的桌子，正在进行中的
    private Map<Integer,CookBoy2DishTable> getUserOpenDishTables(long userId){
        Map<Integer,CookBoy2DishTable> res = new ConcurrentHashMap<>();
        if(!cookBoyTableMap.containsKey(userId)){
            return res;
        }
        for(CookBoy2DishTable temp : cookBoyTableMap.get(userId).values()){
            if(temp.getOverTime() == 0){
                res.put(temp.getNo(),temp);
            }
        }
        return res;
    }
    private Map<Integer,CookBoy2DishTable> getUserDishTables(long userId,int page,int num){
        Map<Integer,CookBoy2DishTable> res = new ConcurrentHashMap<>();
        if(!cookBoyTableMap.containsKey(userId)){
            return res;
        }
        List<CookBoy2DishTable> cookBoy2DishTableList = new ArrayList<>(cookBoyTableMap.get(userId).values());
        cookBoy2DishTableList.sort(new TableSort());
        int count = cookBoy2DishTableList.size();
        int index = (page - 1) * num;
        int resCount = 0;
        for(;index < count + num;index++){
            if(resCount++ == num){
                break;
            }
            if(cookBoy2DishTableList.size() > index){
                CookBoy2DishTable temp = cookBoy2DishTableList.get(index);
                res.put(temp.getNo(),temp);
            }else{
                break;
            }
        }
        return res;
    }
    //从大
    static class TableSort implements Comparator<CookBoy2DishTable> {
        @Override
        public int compare(CookBoy2DishTable o1, CookBoy2DishTable o2) {
            if (o1.getNo() == o2.getNo()) {
                return 0;
            }
            if (o1.getNo() < o2.getNo()) {
                return 1;
            }
            return -1;
        }
    }

    private CookBoyProto.CookBoy2UserIdTableRespMsg.Builder getTablesMsg(long serverId, long homeUserId,int page,int num){
        if(page == 0){
            page = 1;
        }
        if(num == 0 || num > 50){
            num = 50;
        }
        Map<Integer,CookBoy2DishTable> tableMap = getUserDishTables(homeUserId,page,num);
        int dishNum = 0;
        if(cookBoyTableMap.containsKey(homeUserId)){
            dishNum = cookBoyTableMap.get(homeUserId).size();
        }
        CookBoyProto.CookBoy2UserIdTableRespMsg.Builder respMsg = CrossCookBoyPb.parseCookBoy2CookerTableRespMsg(tableMap,getActivityId(),serverId,homeUserId,dishNum,0);
        for(Integer spoonId : cookerMap.get(homeUserId).getForbiddenSpoonList()){
            respMsg.addForbidSpoonId(spoonId);
        }
        return respMsg;
    }


    public void syncCookerHomeTable(long serverId,long userId,long homeUserId,int page,int num){
        tableCheck();
        CookBoyProto.CookBoy2UserIdTableRespMsg.Builder respMsg = getTablesMsg(cookerMap.get(homeUserId).getServerId(),homeUserId,page,num);
        respMsg.setIsSync(false);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_TABLE_INFO, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        //检查玩家基础数据
        for (CookBoyProto.CookBoy2TableTempMsg msg : respMsg.getTableListList()) {
            for (CookBoyProto.CookBoy2TableJoinerTempMsg tempMsg : msg.getJoinerListList()) {
                if(tempMsg.getUserInfo().getUserAliasId() == 0){
                    //拉取玩家基础信息
                    UnionActivityGroupProto.CrossGetUserBaseInfoReqMsg.Builder toGame = UnionActivityGroupProto.CrossGetUserBaseInfoReqMsg.newBuilder();
                    toGame.addUserId(tempMsg.getUserId());
                    toGame.setActivityId(activityInfo.getActivityId());
                    toGame.setGroupId(0);
                    MessageHelper.sendPacket(tempMsg.getServerId(), 0, YanQuMessageUtils.buildMessage(Protocol.S_UNION_ACTIVITY_GROUP_GET_USER_INFO_FROM_CROSS, toGame));
                }
            }
        }
    }

    public void getCookerTable(long serverId,long userId,long homeUserId,int tableId){
        CookBoy2DishTable cookBoy2DishTable = null;
        if(cookBoyTableMap.containsKey(homeUserId) && cookBoyTableMap.get(homeUserId).containsKey(tableId)){
            cookBoy2DishTable = cookBoyTableMap.get(homeUserId).get(tableId);
        }
        CookBoyProto.CookBoy2UserTableInfoRespMsg.Builder respMsg = CrossCookBoyPb.parseCookBoy2RecordRespMsg(cookBoy2DishTable);
        if(respMsg != null){
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_USER_TABLE_INFO_REQ, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    public void syncCookerTable(long serverId,long userId){
//        cookerRanking();
        tableCheck();
        CookBoyProto.CookBoy2CookerRespMsg.Builder respMsg = CookBoyProto.CookBoy2CookerRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setActivityId(activityInfo.getActivityId());
        for(CookBoyUpUser cookBoy2User : cookerMap.values()){
            CookBoyProto.CookBoy2CookerTempMsg.Builder tempFoodMsg = CookBoyProto.CookBoy2CookerTempMsg.newBuilder();
            tempFoodMsg.setServerId(cookBoy2User.getServerId());
            tempFoodMsg.setUserId(cookBoy2User.getUserId());
            tempFoodMsg.setCanEat(isOpenTableCanEat(cookBoy2User.getUserId(),userId));
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(cookBoy2User.getUserId());
            if(userBaseInfo == null){
                continue;
            }
            tempFoodMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            tempFoodMsg.setRank(cookBoy2User.getRank());
            tempFoodMsg.setActivityId(activityInfo.getActivityId());
            respMsg.addCookerList(tempFoodMsg);
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_TABLE_USER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    private boolean isOpenTableCanEat(long userId,long joinUserId){
        if(cookBoyTableMap.containsKey(userId)){
            Map<Integer, CookBoy2DishTable> tempMap = cookBoyTableMap.get(userId);
            for(CookBoy2DishTable cookBoy2DishTable : tempMap.values()){
                CookBoy2DishConfig cookBoy2DishConfig = CrossCookBoyActivityMgr.getDishCondfig(getActivityId(),cookBoy2DishTable.getDishId());
                if(cookBoy2DishTable.getOverTime() == 0 && cookBoy2DishTable.getCookBoy2JoinerMap().size() < cookBoy2DishConfig.getSeat()){
                    if(!cookBoy2DishTable.getCookBoy2JoinerMap().containsKey(joinUserId)){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public void getRecord(long serverId,long userId){
        tableCheck();
        CookBoyProto.CookBoy2RecordRespMsg.Builder respMsg = CookBoyProto.CookBoy2RecordRespMsg.newBuilder();
        respMsg.setRet(0);
        for(CookBoy2UserJoinData cookBoy2UserJoinData : new ArrayList<>(joinList)){
            if(cookBoy2UserJoinData.getUserId1() == userId && cookBoy2UserJoinData.getActivityId() ==getActivityId()){
                CookBoyProto.BanquetRelationshipTemp.Builder temp = CookBoyProto.BanquetRelationshipTemp.newBuilder();
                temp.setUserId(cookBoy2UserJoinData.getUserId2());
                temp.setTo(cookBoy2UserJoinData.getJoinTime1());
                temp.setFrom(cookBoy2UserJoinData.getJoinTime2());
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(cookBoy2UserJoinData.getUserId2());
                if(userBaseInfo != null){
                    temp.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                }
                temp.setBanquetId(isOpenTableCanEat(cookBoy2UserJoinData.getUserId2(),cookBoy2UserJoinData.getUserId1())?"1":"0");
                respMsg.addRecordList(temp);
            }else if(cookBoy2UserJoinData.getUserId2() == userId && cookBoy2UserJoinData.getActivityId() ==getActivityId()){
                CookBoyProto.BanquetRelationshipTemp.Builder temp = CookBoyProto.BanquetRelationshipTemp.newBuilder();
                temp.setUserId(cookBoy2UserJoinData.getUserId1());
                temp.setTo(cookBoy2UserJoinData.getJoinTime2());
                temp.setFrom(cookBoy2UserJoinData.getJoinTime1());
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(cookBoy2UserJoinData.getUserId1());
                if(userBaseInfo != null){
                    temp.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                }
                temp.setBanquetId(isOpenTableCanEat(cookBoy2UserJoinData.getUserId1(),cookBoy2UserJoinData.getUserId2())?"1":"0");
                respMsg.addRecordList(temp);
            }
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_JOIN_RECORD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //获取某个用户有几张桌子可以试吃
    private int getUserEatNum(long userId,long joinUserId){
        int count = 0;
        if(cookBoyTableMap.containsKey(userId)){
            Map<Integer, CookBoy2DishTable> tableMap = cookBoyTableMap.get(userId);
            for(CookBoy2DishTable cookBoy2DishTable : tableMap.values()){
                CookBoy2DishConfig cookBoy2DishConfig = CrossCookBoyActivityMgr.getDishCondfig(getActivityId(),cookBoy2DishTable.getDishId());
                if(cookBoy2DishTable.getOverTime() == 0 && cookBoy2DishTable.getCookBoy2JoinerMap().size() <= cookBoy2DishConfig.getSeat()){
                    if(!cookBoy2DishTable.getCookBoy2JoinerMap().containsKey(joinUserId)){
                        count++;
                    }
                }
            }
        }
        return count;
    }

    public void getUnionRelation(long serverId,long userId, List<Long> unionList,List<Long> relationList){
        tableCheck();
        CookBoyProto.CookBoy2SearchRespMsg.Builder respMsg = CookBoyProto.CookBoy2SearchRespMsg.newBuilder();
        respMsg.setRet(0);
        for(Long unionUserId : unionList){
            CookBoyProto.CookBoy2SearchTempMsg.Builder temp = CookBoyProto.CookBoy2SearchTempMsg.newBuilder();
            temp.setUserId(unionUserId);
            temp.setEatNum(getUserEatNum(unionUserId,userId));
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(unionUserId);
            if(userBaseInfo == null){
                continue;
            }
            temp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            if (autoJoinSpoonMap.containsKey(unionUserId)) { // 商会自动回访汤勺
                CrossCookBoy2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(unionUserId);
                if (autoJoinSpoon != null && autoJoinSpoon.getSpoonMap() != null) {
                    for (Map.Entry<Integer, Integer> kv : autoJoinSpoon.getSpoonMap().entrySet()) {
                        CookBoyProto.CookBoy2SpoonTempMsg.Builder spoonTemp =
                                CookBoyProto.CookBoy2SpoonTempMsg.newBuilder();
                        spoonTemp.setId(kv.getKey());
                        spoonTemp.setCnt(kv.getValue());
                        temp.addAutoJoinSpoon(spoonTemp);
                    }
                }
            }
            respMsg.addUnionList(temp);
        }
        for(Long relationUserId : relationList){
            CookBoyProto.CookBoy2SearchTempMsg.Builder temp = CookBoyProto.CookBoy2SearchTempMsg.newBuilder();
            temp.setUserId(relationUserId);
            temp.setEatNum(getUserEatNum(relationUserId,userId));
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(relationUserId);
            if(userBaseInfo == null){
                continue;
            }
            temp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            if (autoJoinSpoonMap.containsKey(relationUserId)) { // 亲友自动回访汤勺
                CrossCookBoy2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(relationUserId);
                if (autoJoinSpoon != null && autoJoinSpoon.getSpoonMap() != null) {
                    for (Map.Entry<Integer, Integer> kv : autoJoinSpoon.getSpoonMap().entrySet()) {
                        CookBoyProto.CookBoy2SpoonTempMsg.Builder spoonTemp =
                                CookBoyProto.CookBoy2SpoonTempMsg.newBuilder();
                        spoonTemp.setId(kv.getKey());
                        spoonTemp.setCnt(kv.getValue());
                        temp.addAutoJoinSpoon(spoonTemp);
                    }
                }
            }
            respMsg.addMarryList(temp);
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_SEARCH_REQ, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void searchUser(long serverId,long userId,String searchUserId){
        tableCheck();
        CookBoyProto.CookBoy2SearchOneRespMsg.Builder respMsg = CookBoyProto.CookBoy2SearchOneRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!StringUtils.isNumber(searchUserId)){
            respMsg.setRet(GameErrorCode.E_COOK_BOY2_USER_NOT_FUND);
        }
        UserBaseInfo selfUserInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(selfUserInfo != null && StringUtils.isNumber(searchUserId) &&  selfUserInfo.getUserAliasId() == Long.valueOf(searchUserId)){
            respMsg.setRet(GameErrorCode.E_COOK_BOY2_SEARCH_USER_SELF);
        }
        if(respMsg.getRet() == 0){
            CookBoyProto.CookBoy2SearchTempMsg.Builder temp = null;
            for(Long homeUserId : new ArrayList<>(cookerMap.keySet())){
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(homeUserId);
                if(userBaseInfo == null){
                    continue;
                }
                if(userBaseInfo.getUserAliasId() ==  Long.parseLong(searchUserId)){
                    temp = CookBoyProto.CookBoy2SearchTempMsg.newBuilder();
                    temp.setUserId(homeUserId);
                    temp.setEatNum(getUserEatNum(homeUserId,userId));
                    temp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                    respMsg.setSearchData(temp);
                    break;
                }
            }
            if(temp == null){
                respMsg.setRet(GameErrorCode.E_COOK_BOY2_USER_NOT_FUND);
            }
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_SEARCH_ONE, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //没用了
    public void addPromotionUser(Map<Integer,Long> userMap){
        for(int rank : userMap.keySet()){
            long userId = userMap.get(rank);
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if(!cookerMap.containsKey(userId)){
                CookBoyUpUser cookBoy2User = new CookBoyUpUser();
                cookBoy2User.setActivityId(activityInfo.getActivityId());
                cookBoy2User.setServerId(userBaseInfo.getServerId());
                cookBoy2User.setUserId(userId);
                cookBoy2User.setPos(rank);
                cookBoy2User.setType(2);
                cookerMap.put(cookBoy2User.getUserId(),cookBoy2User);
                synchronized (needInsertUserList){
                    needInsertUserList.add(cookBoy2User);
                }
            }
        }
    }

    //自己有什么钥匙，是不是能吃
    private boolean canJoinSpoon(long homeUserId,List<Integer> spoonIdList){
        CookBoyUpUser cookData = cookerMap.get(homeUserId);
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if(cookData != null){
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
            for(int spoonId : spoonIdList){
                if(!forbidSpoonIdList.contains(spoonId)){
                    return true;
                }
            }
        }
        return false;
    }
    private RandomHelper randomHelper = new RandomHelper();

    //获取一个随机的自己可以参加的玩家
    public void getRandomCanJoinUser(long serverId,long userId,long nowUserId,List<Integer> spoonIdList){
        CookBoyProto.CookBoy2CanJoinUserRespMsg.Builder respMsg = CookBoyProto.CookBoy2CanJoinUserRespMsg.newBuilder();
        respMsg.setRet(GameErrorCode.E_COOK_BOY2_GET_CAN_JOIN_USER_NO);
        List<Long> userIdList = new ArrayList<>(openCookBoyTableMap.keySet());
        userIdList.remove(nowUserId);
        while (userIdList.size() > 0){
            int randomIndex = randomHelper.next(0,userIdList.size());
            long homeUserId = userIdList.get(randomIndex);
            userIdList.remove(randomIndex);
            if(homeUserId != userId && homeUserId != nowUserId) {
                if(!canJoinSpoon(homeUserId,spoonIdList))continue;
                for (CookBoy2DishTable cookBoy2DishTable : new ArrayList<>(openCookBoyTableMap.get(homeUserId).values())) {
                    Map<Long, CookBoy2Joiner> userIdlList = cookBoy2DishTable.getCookBoy2JoinerMap();
                    if (!userIdlList.containsKey(userId)) {
                        respMsg.setRet(0);
                        CookBoyProto.CookBoy2CookerTempMsg.Builder userInfo = CookBoyProto.CookBoy2CookerTempMsg.newBuilder();
                        userInfo.setServerId(cookBoy2DishTable.getServerId());
                        userInfo.setUserId(cookBoy2DishTable.getUserId());
                        userInfo.setCanEat(true);
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(cookBoy2DishTable.getUserId());
                        if (userBaseInfo == null) {
                            continue;
                        }
                        userInfo.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                        userInfo.setActivityId(activityInfo.getActivityId());
                        respMsg.setUserInfo(userInfo);
                        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_CAN_JOIN_USER, respMsg);
                        MessageHelper.sendPacket(serverId, userId, pbMsg);
                        return;
                    }
                }
            }
        }
        /*for(long homeUserId : new ArrayList<>(openCookBoyTableMap.keySet())){
            if(homeUserId != userId && homeUserId != nowUserId) {
                if(!canJoinSpoon(homeUserId,spoonIdList))continue;
                for (CookBoy2DishTable cookBoy2DishTable : new ArrayList<>(openCookBoyTableMap.get(homeUserId).values())) {
                    Map<Long, CookBoy2Joiner> userIdlList = cookBoy2DishTable.getCookBoy2JoinerMap();
                    if (!userIdlList.containsKey(userId)) {
                        respMsg.setRet(0);
                        CookBoyProto.CookBoy2CookerTempMsg.Builder userInfo = CookBoyProto.CookBoy2CookerTempMsg.newBuilder();
                        userInfo.setServerId(cookBoy2DishTable.getServerId());
                        userInfo.setUserId(cookBoy2DishTable.getUserId());
                        userInfo.setCanEat(true);
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(cookBoy2DishTable.getUserId());
                        if (userBaseInfo == null) {
                            continue;
                        }
                        userInfo.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                        respMsg.setUserInfo(userInfo);
                        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_CAN_JOIN_USER, respMsg);
                        MessageHelper.sendChannelPacket(serverId, userId, pbMsg);
                        return;
                    }
                }
            }
        }*/
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_CAN_JOIN_USER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }


    //设置汤勺类型，别人不能用这个类型入座
    public void forbidSpoon(long serverId,long userId,List<Integer> forbidSpoonIdList){
        CookBoyUpUser userData = cookerMap.get(userId);
        if(userData != null){
            userData.setForbiddenSpoonList(forbidSpoonIdList);
            synchronized (needUpdateUserList){
                if(!needUpdateUserList.contains(userData)){
                    needUpdateUserList.add(userData);
                }
            }
            CookBoyProto.CookBoy2ForbidSpoonRespMsg.Builder respMsg = CookBoyProto.CookBoy2ForbidSpoonRespMsg.newBuilder();
            respMsg.setRet(0);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_COOK_BOY2_FORBID_SPOON, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    //按照排名给桌子排下序
    private void rankToPos(){
        List<CookBoyUpUser> upUserList = new ArrayList<>(cookerMap.values());
        upUserList.sort(new CrossCookBoy3.PosSort());
        int rank = 1;
        for(CookBoyUpUser cookBoyUpUser : upUserList){
            cookBoyUpUser.setRank(rank);
            cookBoyUpUser.setPos(rank);
            rank++;
        }
    }

    //从大到小
    static class PosSort implements Comparator<CookBoyUpUser> {
        @Override
        public int compare(CookBoyUpUser o1, CookBoyUpUser o2) {
            if (o1.getLastScore() == o2.getLastScore()) {
                return 0;
            }
            if (o1.getLastScore() <= o2.getLastScore()) {
                return 1;
            }
            return -1;
        }
    }
    public void addPromotionUser(long serverId,List<CookBoyProto.CrossCookBoyWindUpCookerTempMsg> userListMsg){
        boolean sortFlag = false;
        for(CookBoyProto.CrossCookBoyWindUpCookerTempMsg tempMsg : userListMsg){
            long userId = tempMsg.getUserId();
            UserBaseInfo userBaseInfo = PlayerBasePb.parseToUserBaseInfo(tempMsg.getPlayerBaseData());
            CrossUserMgr.updateUserBaseInfo(userId,userBaseInfo);
            if(!cookerMap.containsKey(userId)){
                sortFlag = true;
                CookBoyUpUser cookBoy2User = new CookBoyUpUser();
                cookBoy2User.setActivityId(activityInfo.getActivityId());
                cookBoy2User.setServerId(serverId);
                cookBoy2User.setUserId(userId);
                cookBoy2User.setPos(cookerMap.size() + 1);
                cookBoy2User.setType(2);
                cookBoy2User.setLastScore(tempMsg.getScore());
                cookBoy2User.setForbiddenSpoonList(new ArrayList<>());
                cookerMap.put(cookBoy2User.getUserId(),cookBoy2User);
                synchronized (needInsertUserList){
                    needInsertUserList.add(cookBoy2User);
                }
            }
        }
        if(sortFlag){
            rankToPos();
        }
    }

    public void timerTask(){
        tableCheck();
        syncHorseNotice();
        activityEndWindUp();
        syncCookerServer();
        syncActivityInfoToServer();
    }

    private void syncActivityInfoToServer() {
        if(syncServerIdList.isEmpty()){
            return;
        }
        CookBoyProto.CrossCookBoy2ActivityInfoSync.Builder builder = CookBoyProto.CrossCookBoy2ActivityInfoSync.newBuilder();
        builder.setActivity(CrossActivityPb.parseActivityTempMsg(activityInfo));
        for (Long sid : new ArrayList<>(syncServerIdList)) {
            MessageHelper.sendPacket(sid, 0, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_ACTIVITY_SYNC, builder));
        }
    }

    public void syncLoginData(){

    }

    public CrossCookBoy2(ActivityInfo acInfo){
        activityInfo = acInfo;
        this.syncServerIdList = new ConcurrentHashSet<>(getNeedSyncServerIdList());
//		reload();
    }

    public void initJonList(List<CookBoy2UserJoinData> joinList){
        for(CookBoy2UserJoinData cookBoy2UserJoinData : joinList){
            joinMap.put(cookBoy2UserJoinData.getUserId1(),cookBoy2UserJoinData);
        }
    }

    private void initOpenTable(){
        for(Map<Integer, CookBoy2DishTable> cookBoy2DishTableMap : cookBoyTableMap.values()){
            for(CookBoy2DishTable cookBoy2DishTable : cookBoy2DishTableMap.values()){
                if(cookBoy2DishTable.getOverTime() == 0){
                    if(!openCookBoyTableMap.containsKey(cookBoy2DishTable.getUserId())){
                        openCookBoyTableMap.put(cookBoy2DishTable.getUserId(),new ConcurrentHashMap<>());
                    }
                    openCookBoyTableMap.get(cookBoy2DishTable.getUserId()).put(cookBoy2DishTable.getNo(),cookBoy2DishTable);
                }
            }
        }
    }

    public boolean reload() {
        cookBoyTableMap = CrossCookBoyBussiness.getCrossDishTableMap(activityInfo.getActivityId());
        cookerMap = CrossCookBoyBussiness.getCrossCookBoyUserMap(activityInfo.getActivityId());

        joinList = CrossCookBoyBussiness.getCookBoy2UserJoinData(getActivityId());
        initJonList(joinList);

        autoJoinSpoonMap = new CrossCommonActivityDataDaoImpl<CrossCookBoy2AutoJoinSpoon>().
                getActivityDataLongMap(CrossCookBoy2AutoJoinSpoon.class, getActivityId(), "userId");

        List<CookBoy2AutoJoinRecord> autoJoinRecords = new CrossCommonActivityDataDaoImpl<CookBoy2AutoJoinRecord>().
                getActivityDataList(CookBoy2AutoJoinRecord.class, getActivityId());

        for (CookBoy2AutoJoinRecord autoJoinRecord : autoJoinRecords) {
            long userId = autoJoinRecord.getUserId();
            long hostId = autoJoinRecord.getHostId();
            if (!autoJoinRecordMap.containsKey(userId)) {
                autoJoinRecordMap.put(userId, new HashMap<>());
            }
            Map<Long, CookBoy2AutoJoinRecord> recordMap = autoJoinRecordMap.get(userId);
            if (!recordMap.containsKey(hostId)) {
                recordMap.put(hostId, autoJoinRecord);
            }
        }

//        repair();
        initOpenTable();
        rankToPos();

        // 初始化自动回宴线程池，开1个线程池，线程数量2个
        if(null == autoJoinThreadPool) {
            autoJoinThreadPool = new ThreadTaskManger(1, "autoJoinThreadPool", 2);
        }
        return true;
    }

    public boolean save() {
        List<CookBoy2DishTable> tempInsertList;
        synchronized (needInsertTableList) {
            tempInsertList = new ArrayList<>(needInsertTableList);
            needInsertTableList.clear();
        }
        if (tempInsertList.size() > 0) {
            CrossCookBoyBussiness.addCrossDishTableList(tempInsertList);
        }
        List<CookBoy2DishTable> tempUpdateList;
        synchronized (needUpdateTableList) {
            tempUpdateList = new ArrayList<>(needUpdateTableList);
            needUpdateTableList.clear();
        }
        if (tempUpdateList.size() > 0) {
            CrossCookBoyBussiness.updateCrossDishTableList(tempUpdateList);
        }
        List<CookBoyUpUser> tempCookBoy2UserInsertList;
        synchronized (needInsertUserList){
            tempCookBoy2UserInsertList = new ArrayList<>(needInsertUserList);
            needInsertUserList.clear();
        }
        if(tempCookBoy2UserInsertList.size() > 0){
            CrossCookBoyBussiness.addCrossCookBoyUserList(tempCookBoy2UserInsertList);
        }
        List<CookBoyUpUser> tempCookBoy2UserUpdateList;
        synchronized (needUpdateUserList){
            tempCookBoy2UserUpdateList = new ArrayList<>(needUpdateUserList);
            needUpdateUserList.clear();
        }
        if(tempCookBoy2UserUpdateList.size() > 0){
            CrossCookBoyBussiness.updateCrossCookBoyUserList(tempCookBoy2UserUpdateList);
        }

        List<CookBoy2UserJoinData> tempJoinInsertList;
        synchronized (joinInsertList) {
            tempJoinInsertList = new ArrayList<>(joinInsertList);
            joinInsertList.clear();
        }
        if (tempJoinInsertList.size() > 0) {
            CrossCookBoyBussiness.addJoinRelationList(tempJoinInsertList);
        }

        List<CookBoy2UserJoinData> tempJoinUpdateList;
        synchronized (joinUpdateList) {
            tempJoinUpdateList = new ArrayList<>(joinUpdateList);
            joinUpdateList.clear();
        }
        if (tempJoinUpdateList.size() > 0) {
            CrossCookBoyBussiness.updateJoinRelationList(tempJoinUpdateList);
        }

        for (CrossCookBoy2AutoJoinSpoon spoon : autoJoinSpoonMap.values()) {
            if (spoon.isUpdateOption()) {
                new CrossCommonActivityDataDaoImpl<CrossCookBoy2AutoJoinSpoon>().update(spoon);
            } else if (spoon.isInsertOption()) {
                new CrossCommonActivityDataDaoImpl<CrossCookBoy2AutoJoinSpoon>().add(spoon);
            }
        }

        for (Map.Entry<Long, Map<Long, CookBoy2AutoJoinRecord>> kv : autoJoinRecordMap.entrySet()) {
            for (CookBoy2AutoJoinRecord record : kv.getValue().values()) {
                if (record.isUpdateOption()) {
                    new CrossCommonActivityDataDaoImpl<CookBoy2AutoJoinRecord>().update(record);
                } else if (record.isInsertOption()) {
                    new CrossCommonActivityDataDaoImpl<CookBoy2AutoJoinRecord>().add(record);
                }
            }
        }

        return true;
    }

    public boolean init() {
        return reload();
    }

    public boolean stop() {
        return false;
    }

    /**
     * 预留接口
     */
    public void repair() {
        String activityIdStr = "9063734,9063735,9063736,9063737,9063738,9063739,9063740,9063741,9063742,9063743,9063744,9063745";
        List<Integer> activityIdList = StringUtils.stringToIntegerList(activityIdStr,",");
        if(!activityIdList.contains(activityInfo.getActivityId()) || System.currentTimeMillis() > 1639555255000L)return;
        CookBoy2Spoon cookBoy2Spoon = CrossCookBoyActivityMgr.getCookBoy2MinSpoon(getActivityId());
        String userIdStr = "101000050006544;101000050006553;101000080005730;101000080008415;101000100008349;101000100008350;101000100008351;101000100008352;101000130000033;101000130000298;101000130000351;101000130000690;101000130000857;101000130001039;101000140000024;101000150007750;101000180002090;101000180004991;101000190001320;101000190005135;101000190010014;101000190013989;101000200006171;101000210000043;101000210003773;101000210011752;101000210012437;101000210012656;101000210012818;101000210012840;101000230002914;101000230007720;101000240004769;101000250000909;101000250006511;101000250006813;101000270001289;101000270004432;101000270004602;101000270009391;101000280002397;101000280006225;101000300006265;101000300007223;101000310006047;101000310006886;101000320003835;101000320005295;101000330004455;101000340000887;101000340002216;101000340004537;101000360002736;101000360006563;101000380005385;101000380006097;101000390002377;101000390002652;101000390007723;101000390007758;101000400004666;101000400007474;101000420000794;101000440002901;101000460007055;101000490001160;101000500008499;101000510004590;101000520000437;101000520006197;101000540002914;101000540008927;101000540008928;101000540008929;101000540008963;101000550003626;101000560000589;101000560000929;101000560000938;101000560010062;101000570001289;101000570006598;101000570009972;101000570010033;101000590003132;101000590008375;101000590008505;101000590009019;101000590009221;101000600004022;101000600004539;101000610002800;101000620000858;101000620002058;101000620009138;101000630000312;101000630002520;101000640006766;101000650000479;101000660008195;101000670006253;101000680004140;101000690008400;101000690008810;101000700000511;101000700008061;101000700008551;101000710005816;101000710005902;101000710008966;101000710012976;101000730000381;101000730007939;101000730008352;101000740003877;101000750006443;101000750006785;101000750007809;101000750008107;101000760000412;101000760003837;101000770001774;101000770002389;101000770004130;101000780008462;101000780008510;101000790003116;101000800000063;101000800004837;101000800005285;101000800007183;101000800007502;101000800007708;101000800007709;101000800007717;101000800007718;101000800007725;101000800007767;101000800007875;101000800007881;101000800007882;101000800007935;101000800007944;101000800007945;101000800007946;101000800007963;101000810004839;101000810007100;101000820000898;101000860003913;101000860004821;101000860007920;101000870004080;101000870008399;101000880000459;101000890006504;101000910002607;101000910006052;101000920000021;101000920001720;101000940001768;101000940004556;101000970004224;101000970006968;101000980005465;101001000001119;101001000001267;101001000002202;101001010003072;101001010005662;101001010005815;101001010007320;101001010007926;101001020000720;101001020008505;101001020008608;101001020008609;101001020008610;101001020008611;101001020008612;101001020008613;101001020008615;101001020008616;101001020008617;101001030002846;101001030008019;101001040000813;101001040001727;101001040001790;101001040007801;101001060006033;101001070007241;101001070008312;101001090002896;101001090003141;101001120000888;101001120001889;101001120005632;101001120008626;101001130000954;101001130004194;101001130005486;101001130006226;101001140000328;101001140005149;101001140005308;101001140006045;101001140008276;101001140008277;101001140008285;101001150005016;101001150008136;101001160002180;101001180001414;101001190007741;101001200003016;101001200006828;101001200009450;101001210000065;101001210009969;101001220004037;101001220005022;101001230007075;101001270000125;101001270001279;101001270004620;101001270005158;101001270005326;101001270006535;101001270006578;101001290007261;101001300003218;101001300003726;101001300007675;101001310003571;101001310004301;101001310005406;101001310007979;101001330000823;101001340002364;101001340003199;101001350001763;101001350007663;101001360006060;101001360006065;101001360008053;101001380000237;101001380001804;101001380002404;101001380002994;101001380007823;101001390004630;101001390008059;101001400000298;101001400004498;101001400005839;101001420008434;101001420008435;101001430000615;101001430001163;101001430002075;101001430002688;101001430002894;101001430003970;101001430006696;101001430007271;101001430008183;101001430008416;101001430008495;101001430008531;101001440001541;101001440005185;101001440007392;101001450005087;101001450006764;101001470001909;101001480008153;101001490000269;101001490001304;101001490007284;101001490007502;101001490007544;101001490008427;101001500003431;101001500007930;101001510002065;101001510002521;101001520006476;101001520006632;101001530004846;101001530007738;101001540001073;101001580000469;101001580004422;101001590008041;101001590008509;101001590008510;101001600003510;101001600005888;101001600007484;101001600007533;101001600007585;101001600008116;101001620005809;101001630001025;101001650000289;101001650004978;101001650006269;101001660001236;101001660002293;101001660003095;101001660005105;101001660006752;101001670000210;101001670007569;101001680000386;101001680002108;101001690004579;101001710001951;101001710002070;101001710009006;101001740001368;101001740002137;101001740005479;101001740008518;101001740008548;101001750000538;101001750000541;101001750001104;101001750003065;101001750004420;101001750004573;101001750005612;101001750006737;101001750007855;101001750008017;101001750008207;101001750008392;101001760003927;101001760007386;101001770004701;101001790007586;101001800002697;101001800007909;101001800007919;101001800007943;101001800008019;101001810002139;101001810004366;101001810006163;101001810009923;101001820006402;101001830000919;101001830002540;101001830002938;101001830004266;101001830007101;101001830008154;101001830008271;101001840005054;101001850001807;101001850002568;101001850003593;101001860000567;101001860002436;101001860007848;101001860008762;101001870003948;101001880002039;101001880002491;101001880005066;101001880007657;101001880008263;101001890001329;101001890003487;101001890006441;101001890006577;101001890007980;101001910004836;101001910005811;101001920002127;101001930008126;101001950001241;101001950001923;101001960002539;101001960003462;101001970004183;101001970006166;101001970008024;101001980000195;101001980006707;101001980007119;101001980007871;101001990006523;101001990007969;101002000000353;101002000004519;101002020006611;101002030008078;101002050003329;101002050006437;101002080004593;101002090001450;101002090007668;101002100000454;101002100000623;101002100000770;101002100003423;101002120002274;101002120003040;101002120004821;101002120005780;101002150005291;101002150005864;101002150012449;101002160006278;101002180000152;101002180000977;101002180001117;101002180001764;101002180005418;101002190002092;101002200001554;101002200006684;101002200008705;101002210001009;101002210001432;101002210010324;101002220005617;101002220007772;101002220008006;101002230002820;101002230005425;101002240000724;101002250002534;101002250006290;101002260003249;101002270000848;101002270002687;101002270003206;101002270006611;101002280001872;101002280002137;101002280007419;101002290001774;101002290004614;101002290005229;101002300001350;101002320002294;101002320003413;101002330002949;101002340005513;101002350001096;101002360004676;101002360006282;101002370003380;101002370005086;101002370006727;101002380000150;101002380001213;101002380002795;101002380002893;101002380003182;101002380005030;101002410000915;101002410001757;101002410001759;101002410001873;101002410007001;101002410007029;101002410007069;101002430002578;101002430004926;101002440000272;101002440006177;101002450005028;101002460004677;101002460007365;101002470004955;101002480004576;101002480006414;101002480006421;101002480006426;101002490002565;101002490004487;101002500003312;101002500003456;101002510001430;101002520002043;101002520002779;101002530004027;101002530004992;101002530005318;101002540004781;101002540005997;101002540006132;101002550000213;101002550005984;101002550006607;101002560003129;101002560006485;101002590000782;101002590002523;101002600004996;101002600005990;101002610005675;101002620000528;101002630002899;101002630002924;101002630002988;101002630006353;101002630007002;101002630007032;101002630007251;101002650000542;101002650002885;101002650003429;101002660000049;101002660005837;101002660005838;101002670001285;101002670004152;101002680001393;101002690000062;101002690000492;101002700000471;101002700000601;101002700002960;101002710000440;101002710000884;101002720003581;101002720003848;101002720005807;101002730000660;101002730001516;101002730002239;101002730005179;101002740003848;101002750002100;101002750003945;101002760000087;101002760000995;101002760002936;101002760004641;101002770000320;101002770001875;101002770005623;101002770005673;101002780000027;101002780001575;101002780005718;101002790000003;101002790000766;101002790002199;101002800000143;101002810000410;101002810000435;101002820002127;101002820005614;101002820006298;101002830005132;101002840003586;101002840004933;101002850004720;101002860000020;101002860001764;101002860003331;101002870001779;101002880000005;101002880000590;101002880000722;101002880001227;101002880001460;101002880002449;101002880002942;101002890001297;101002900000364;101002900002055;101002900002349;101002910001546";
        List<Long> userIdList = StringUtils.stringToLongList(userIdStr,";");
        for(Long userId : userIdList){
            logger.error(userId + "玩家开始修复");
            Map<Integer, CookBoy2DishTable> tableMap = cookBoyTableMap.get(userId);
            if(tableMap == null)continue;
            for(CookBoy2DishTable table : tableMap.values()){
                if(table.getOverTime() != 0){
                    logger.error(userId + "玩家修复"+table.getUserDishId()+"菜");
                    CookBoyProto.CrossCookBoy2RobotJoinBanquetMsg.Builder msg = CookBoyProto.CrossCookBoy2RobotJoinBanquetMsg.newBuilder();
                    msg.setRet(0);
                    msg.setActivityId(getActivityId());
                    msg.setHomeUserId(userId);
                    msg.setDishId(table.getDishId());
                    msg.setIntegral(0);
                    msg.setTableId(table.getNo());
                    msg.setUserDishId(table.getUserDishId());
                    msg.setAllIntegral(table.getIntegral());
                    synchronized (table){
                        long allRobotIntegral = 0;
                        Map<Long, CookBoy2Joiner> joinerMap = table.getCookBoy2JoinerMap();
                        for(CookBoy2Joiner joiner : joinerMap.values()){
                            if(joiner.getRobotId() != 0){
                                allRobotIntegral += cookBoy2Spoon.getUserIntegral() * CrossCookBoyActivityMgr.getCookBoy2RobotAdd(getActivityId()) / 1000;
                            }
                        }
                        msg.setIntegral(allRobotIntegral);
                    }
                    YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_ROBOT_JOIN, msg);
                    synchronized (endTableMsgMap) {
                        endTableMsgMap.put(table,pbOpenerMsg);
                    }
                }
            }
        }
    }

    public List<Long> getNeedSyncServerIdList(){
        if(activityInfo.getServerIdList2().isEmpty()){
            return Collections.emptyList();
        }
        List<Long> list = new ArrayList<>();
        for (Long id : activityInfo.getServerIdList2()) {
            if(activityInfo.getServerIdList().contains(id)){
                continue;
            }
            list.add(id);
        }
        return list;
    }

    /**
     * 自动回访试吃
     *
     * @param serverId 回发游戏服ID
     * @param reqMsg  reqMsg
     */
    public void autoJoinTaste(long serverId, CookBoyProto.CrossCookBoy2AutoJoinTasteMsg reqMsg) {
        CookBoyProto.CrossCookBoy2AutoJoinInfoMsg autoJoinInfo = reqMsg.getAutoJoinInfo();
        long hostId = autoJoinInfo.getHostId();
        long guestId = autoJoinInfo.getGuestId();
        int hostActivityId = autoJoinInfo.getHostActivityId();
        int guestActivityId = autoJoinInfo.getGuestActivityId();
        int spoonId = autoJoinInfo.getSpoonId();
        int spoonCnt = reqMsg.getSpoonCnt();

        if (!cookBoyTableMap.containsKey(hostId)) {
            logger.error("摊主桌子信息未找到! 活动ID:{} 摊主ID:{}", hostActivityId, hostId);
            return;
        }

        CookBoy2Spoon cookBoy2Spoon = CrossCookBoyActivityMgr.getCookBoy2Spoon(hostActivityId, spoonId);
        if (cookBoy2Spoon == null) {
            logger.error("汤勺配置未找到! 活动ID:{} 摊主ID:{} 汤勺ID:{}", hostActivityId, hostId, spoonId);
            return;
        }

        CookBoy2UserInfo hostBaseInfo = new CookBoy2UserInfo(hostActivityId, spoonId, hostId, autoJoinInfo.getHostServerId());
        CookBoy2UserInfo guestBaseInfo = new CookBoy2UserInfo(guestActivityId, spoonId, guestId, serverId);

        int realCost = 0; // 实际试吃的数量
        for (CookBoy2DishTable cookBoy2DishTable : openCookBoyTableMap.get(hostId).values()) {
            synchronized (cookBoy2DishTable) {
                Map<Long, CookBoy2Joiner> joinerMap = cookBoy2DishTable.getCookBoy2JoinerMap();
                if (cookBoy2DishTable.getOverTime() != 0) { // 桌子试吃时间结束
                    continue;
                }
                CookBoy2DishConfig cookBoy2DishConfig = CrossCookBoyActivityMgr.getDishCondfig(getActivityId(), cookBoy2DishTable.getDishId());
                if (cookBoy2DishConfig == null) { // 桌子类型配置未找到
                    continue;
                }
                if (cookBoy2DishTable.getCookBoy2JoinerMap().size() >= cookBoy2DishConfig.getSeat()) { // 满座
                    continue;
                }
                if (!CrossCookBoyActivityMgr.isActivityMatchTime(activityInfo)) { // 不在活动匹配期间
                    continue;
                }
                if (joinerMap.containsKey(guestId)) { // 访客已在阵中
                    continue;
                }

                try {
                    taste(cookBoy2DishTable, cookBoy2Spoon, hostBaseInfo, guestBaseInfo);
                } catch (Exception e) { // 有异常就跳过这一桌
                    logger.error("小当家二阶段自动回访试吃错误！摊主活动ID:{} 摊主ID:{} 访客活动ID:{} 访客ID:{} 菜桌Id:{} 汤勺ID:{}",
                            hostActivityId, hostId, guestActivityId, guestId, cookBoy2DishTable.getDishId(), spoonId);
                    continue;
                }
                realCost++;
                if (realCost == spoonCnt) { // 吃够携带来的汤勺数就提前结束
                    break;
                }
            }
        }

        tableCheck();

        int itemId = CrossCookBoyActivityMgr.getCookBoy2IntegralItemId(guestActivityId); // 收益道具Id
        // 收益回区服发邮件
        if (realCost > 0) {
            Property hostProperty =
                    new Property(itemId, cookBoy2Spoon.getUserIntegral());
            sendReward(spoonId, realCost, hostBaseInfo, hostProperty);

            Property guestProperty =
                    new Property(itemId, cookBoy2Spoon.getJoinerIntegral());
            sendReward(spoonId, realCost, guestBaseInfo, guestProperty);
        }

        CookBoyProto.CrossCookBoy2SyncAutoJoinResultMsg.Builder req =
                CookBoyProto.CrossCookBoy2SyncAutoJoinResultMsg.newBuilder();
        req.setAutoJoinInfo(autoJoinInfo);
        req.setRestCnt(spoonCnt - realCost); // 返还剩余汤勺数
        req.setRealCnt(realCost);

        YanQuMessage pbReq = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_SYNC_AUTO_JOIN_RESULT, req);
        MessageHelper.sendPacket(serverId, guestId, pbReq);
    }

    /**
     * 同步自动回访数据
     *
     * @param serverId 访客服务器ID
     * @param reqMsg   reqMsg
     */
    public void syncAutoJoinData(long serverId, CookBoyProto.CrossCookBoy2SyncAutoJoinDataMsg reqMsg) {
        CookBoyProto.CrossCookBoy2AutoJoinInfoMsg info = reqMsg.getAutoJoinInfo();
        int spoonId = info.getSpoonId();
        long hostId = info.getHostId();
        long guestId = info.getGuestId();
        int guestActivityId = info.getGuestActivityId();

        // 同步汤勺数量
        List<Integer> spoonIds = CrossCookBoyActivityMgr.getCookBoy2SpoonIds(guestActivityId);
        syncSpoonMap(reqMsg.getSpoonList(), guestId, spoonIds, guestActivityId);
        // 修改自动回访记录
        int realCnt = reqMsg.getRealCnt();
        if (!autoJoinRecordMap.containsKey(guestId)) {
            autoJoinRecordMap.put(guestId, new HashMap<>());
        }

        Map<Long, CookBoy2AutoJoinRecord> guestRecordMap = autoJoinRecordMap.get(guestId);
        if (guestRecordMap.containsKey(hostId)) {
            CookBoy2AutoJoinRecord record = guestRecordMap.get(hostId);
            if (record != null) {
                record.getSpoonMap().merge(spoonId, realCnt, Integer::sum); // 回访记录
                record.setLastJoinTime(System.currentTimeMillis());
            }
        } else {
            CookBoy2AutoJoinRecord record = new CookBoy2AutoJoinRecord();
            record.setActivityId(info.getGuestActivityId());
            record.setUserId(guestId);
            record.setServerId(serverId);
            record.setHostActivityId(info.getHostActivityId());
            record.setHostId(hostId);
            record.setHostServerId(info.getHostServerId());
            ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
            List<Integer> confSpoonIds = CrossCookBoyActivityMgr.getCookBoy2SpoonIds(guestActivityId);
            for (int confSpoonId : confSpoonIds) {
                map.put(confSpoonId, 0);
            }
            record.setSpoonMap(map);
            record.getSpoonMap().merge(spoonId, realCnt, Integer::sum); // 回访记录
            record.setLastJoinTime(System.currentTimeMillis());
            guestRecordMap.put(hostId, record);
            record.setInsertOption();
        }
    }

    /**
     * 同步自动回访汤勺数量
     */
    public void syncAutoJoinSpoon(long serverId, CookBoyProto.CrossCookBoy2SyncAutoJoinSpoonMsg reqMsg) {
        int activityId = reqMsg.getActivityId();
        long userId = reqMsg.getUserId();
        List<Integer> spoonIds = CrossCookBoyActivityMgr.getCookBoy2SpoonIds(activityId);
        if (!autoJoinSpoonMap.containsKey(userId)) {
            CrossCookBoy2AutoJoinSpoon tmp = new CrossCookBoy2AutoJoinSpoon(activityId, userId, 0);
            ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
            for (Integer spoonId : spoonIds) {
                map.put(spoonId, 0);
            }
            tmp.setServerId(serverId);
            tmp.setSpoonMap(map);
            autoJoinSpoonMap.put(userId, tmp);
        }

        List<CookBoyProto.CookBoy2SpoonTempMsg> spoonList = reqMsg.getSpoonList();
        syncSpoonMap(spoonList, userId, spoonIds, activityId);
    }

    /**
     * 同步汤勺数量
     *
     * @param spoonList  汤勺列表
     * @param userId     访客ID
     * @param spoonIds   汤勺配置ID
     * @param activityId 访客活动ID
     */
    private void syncSpoonMap(List<CookBoyProto.CookBoy2SpoonTempMsg> spoonList, long userId, List<Integer> spoonIds, int activityId) {
        CrossCookBoy2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(userId);
        ConcurrentHashMap<Integer, Integer> tmpSpoonMap = new ConcurrentHashMap<>();
        for (CookBoyProto.CookBoy2SpoonTempMsg spoon : spoonList) {
            int id = spoon.getId();
            int cnt = spoon.getCnt();
            if (!spoonIds.contains(id)) {
                logger.error("自动回访汤勺数量同步失败，不正确的汤勺ID 活动ID:{} 访客ID:{} 汤勺ID:{} 配置汤勺列表:{}",
                        activityId, userId, id, spoonIds);
                continue;
            }
            tmpSpoonMap.put(id, cnt);
        }
        autoJoinSpoon.setSpoonMap(tmpSpoonMap);
    }

    /**
     * 自动回访试吃，基本是joinTable的原有逻辑
     *
     * @param cookBoy2DishTable 菜桌
     * @param cookBoy2Spoon     汤勺
     * @param host              摊主
     * @param guest             访客
     */
    private void taste(CookBoy2DishTable cookBoy2DishTable, CookBoy2Spoon cookBoy2Spoon,
                       CookBoy2UserInfo host, CookBoy2UserInfo guest) {
        CookBoyUpUser cookData = cookerMap.get(host.getUserId());
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if (cookData != null) {
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
        }

        CookBoy2Joiner cookBoy2Joiner = new CookBoy2Joiner();
        cookBoy2Joiner.setServerId(guest.getServerId());
        cookBoy2Joiner.setUserId(guest.getUserId());
        cookBoy2Joiner.setGifttId(host.getSpoonId());
        Map<Long, CookBoy2Joiner> joinerMap = cookBoy2DishTable.getCookBoy2JoinerMap();
        cookBoy2Joiner.setPos(joinerMap.size() + 1);
        joinerMap.put(cookBoy2Joiner.getUserId(), cookBoy2Joiner); // 上座
        cookBoy2DishTable.setCookBoy2JoinerMap(joinerMap);
        cookBoy2DishTable.setIntegral(cookBoy2DishTable.getIntegral() + cookBoy2Spoon.getUserIntegral());

        CookBoyProto.CrossCookBoy2JoinTableMsg.Builder joinMsg = CookBoyProto.CrossCookBoy2JoinTableMsg.newBuilder();
        joinMsg.setRet(0);
        joinMsg.setActivityId(getActivityId());
        joinMsg.setJoinerUserId(guest.getUserId());
        joinMsg.setHomeUserId(host.getUserId());
        joinMsg.setTableId(cookBoy2DishTable.getDishId());
        joinMsg.setSpoonId(host.getSpoonId());
        joinMsg.addAllForbidSpoonId(forbidSpoonIdList);
        if (guest.getActivityId() > 0) {
            joinMsg.setActivityId(guest.getActivityId());
            joinMsg.setOtherActivityId(host.getActivityId());
        }
        joinMsg.setAutoJoin(1);
        YanQuMessage pbJoinerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_JOIN_JOINER, joinMsg);

        CookBoyProto.CrossCookBoy2JoinTableMsg.Builder msg = CookBoyProto.CrossCookBoy2JoinTableMsg.newBuilder();
        msg.setRet(0);
        msg.setActivityId(getActivityId());
        msg.setJoinerUserId(guest.getUserId());
        msg.setHomeUserId(host.getUserId());
        msg.setTableId(cookBoy2DishTable.getDishId());
        msg.setSpoonId(host.getSpoonId());
        msg.addAllForbidSpoonId(forbidSpoonIdList);
        msg.setAutoJoin(1);
        YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_JOIN_OPENER, msg);
        MessageHelper.sendPacket(guest.getServerId(), guest.getUserId(), pbJoinerMsg);
        MessageHelper.sendPacket(cookBoy2DishTable.getServerId(), host.getUserId(), pbOpenerMsg);

        newJoin(host.getUserId(), guest.getUserId(), guest.getActivityId()); // 添加回宴次数
        syncTableServer(cookBoy2DishTable, cookBoy2Spoon.getUserIntegral());
//        tableCheck();
        synchronized (needUpdateTableList) {
            if (!needUpdateTableList.contains(cookBoy2DishTable)) {
                needUpdateTableList.add(cookBoy2DishTable);
            }
        }
        synchronized (needSyncUserList) {
            if (!needSyncUserList.contains(cookerMap.get(host.getUserId()))) {
                needSyncUserList.add(cookerMap.get(host.getUserId()));
            }
        }

        addAutoJoinLog(cookBoy2DishTable.getNo(), host, guest);
    }

    /**
     * 添加加自动回访记录
     *
     * @param tableId 菜桌ID
     * @param host    摊主
     * @param guest   访客
     */
    private void addAutoJoinLog(int tableId, CookBoy2UserInfo host, CookBoy2UserInfo guest) {
        LogCookBoy2AutoJoin log = new LogCookBoy2AutoJoin(guest.getActivityId(), guest.getUserId(), guest.getServerId(), host.getActivityId(),
                host.getUserId(), host.getServerId(), host.getSpoonId(), tableId, System.currentTimeMillis());
        CrossAutoLogMgr.add(log);
    }

    /**
     * 发送给区服，去区服发送回访收益邮件
     *
     * @param spoonId  汤勺ID
     * @param count    回访次数
     * @param userInfo 用户信息
     * @param property 单项收益
     */
    private static void sendReward(int spoonId, int count, CookBoy2UserInfo userInfo, Property property) {
        CookBoyProto.CrossCookBoy2DealAutoJoinRewardMsg.Builder req =
                CookBoyProto.CrossCookBoy2DealAutoJoinRewardMsg.newBuilder();
        req.setActivityId(userInfo.getActivityId());
        req.setUserId(userInfo.getUserId());
        req.setReward(property.toHelperString());
        req.setSpoonId(spoonId);
        req.setCount(count);

        YanQuMessage pbReq = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_DEAL_AUTO_JOIN_REWARD, req);
        MessageHelper.sendPacket(userInfo.getServerId(), userInfo.getUserId(), pbReq);
    }

    /**
     * 获取自动回访记录
     *
     * @param serverId 服务器ID
     * @param userId   用户ID
     */
    public void getAutoJoinRecord(long serverId, long userId) {
        CookBoyProto.CookBoy2GetAutoJoinRecordRespMsg.Builder respMsg = CookBoyProto.CookBoy2GetAutoJoinRecordRespMsg.newBuilder();
        respMsg.setRet(0);

        if (autoJoinRecordMap.containsKey(userId)) {
            for (CookBoy2AutoJoinRecord record : autoJoinRecordMap.get(userId).values()) {
                CookBoyProto.CookBoy2AutoJoinRecordTemp.Builder recordTemp =
                        CookBoyProto.CookBoy2AutoJoinRecordTemp.newBuilder();
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(record.getHostId()); // 摊主信息
                if (userBaseInfo != null) {
                    recordTemp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                }
                for (Map.Entry<Integer, Integer> kv : record.getSpoonMap().entrySet()) {
                    CookBoyProto.CookBoy2SpoonTempMsg.Builder spoon = CookBoyProto.CookBoy2SpoonTempMsg.newBuilder();
                    spoon.setId(kv.getKey());
                    spoon.setCnt(kv.getValue());
                    recordTemp.addSpoon(spoon);
                }
                respMsg.addRecord(recordTemp);
            }
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_COOK_BOY2_GET_AUTO_JOIN_RECORD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    /**
     * 获取摊主可试吃数量
     *
     * @param serverId 回发游戏服ID
     * @param reqMsg   reqMsg
     */
    public void getTasteTableCnt(long serverId, CookBoyProto.CrossCookBoy2GetTasteTableCntMsg reqMsg) {
        CookBoyProto.CrossCookBoy2AutoJoinInfoMsg autoJoinInfo = reqMsg.getAutoJoinInfo();
        long hostId = autoJoinInfo.getHostId();
        long guestId = autoJoinInfo.getGuestId();
        int spoonId = autoJoinInfo.getSpoonId();

        PlayerProto.PlayerBaseTempMsg guestInfoMsg = autoJoinInfo.getGuestInfo();
        UserBaseInfo guestInfo = PlayerBasePb.parseBaseUserInfo(guestInfoMsg);
        CrossUserMgr.updateUserBaseInfo(guestId, guestInfo);

        CookBoyProto.CrossCookBoy2SyncTasteTableCntMsg.Builder req = CookBoyProto.CrossCookBoy2SyncTasteTableCntMsg.newBuilder();
        req.setRet(0);
        List<Integer> hostForbiddenSpoonIdList = getUserForbiddenSpoonIdList(hostId);
        if (hostForbiddenSpoonIdList.contains(spoonId)) {
            logger.info("摊主设置禁止该类型的汤勺自动回访，无法自动回访。 访客活动ID:{} 访客ID:{} 摊主活动ID:{} 摊主ID:{} 汤勺ID:{}",
                    autoJoinInfo.getGuestActivityId(), guestId, autoJoinInfo.getHostActivityId(), hostId, spoonId);
            return;
        }

        req.setAutoJoinInfo(autoJoinInfo);
        req.setCnt(getUserEatNum(hostId, guestId) <= 0 ? 0 : 1); // 只回宴一次，之前回宴要吃掉摊主所有的菜
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_SYNC_TASTE_TABLE_CNT, req);
        MessageHelper.sendPacket(serverId, guestId, pbMsg);
    }

    /**
     * 活动过期将设置的自动回访汤勺返回
     *
     * @param activityId 活动ID
     */
    public void sendAutoJoinSpoonRest(int activityId) {
        for (CrossCookBoy2AutoJoinSpoon spoon : autoJoinSpoonMap.values()) {
            if (spoon.getActivityId() != activityId) {
                continue;
            }
            if (spoon.getIsReturn() == 1) {
                continue;
            }

            CookBoyProto.CrossCookBoy2DealAutoJoinSpoonRestMsg.Builder respMsg =
                    CookBoyProto.CrossCookBoy2DealAutoJoinSpoonRestMsg.newBuilder();

            respMsg.setActivityId(spoon.getActivityId());
            respMsg.setUserId(spoon.getUserId());

            Map<Integer, Integer> spoonCntMap = new HashMap<>();
            List<Integer> confSpoonIds = CrossCookBoyActivityMgr.getCookBoy2SpoonIds(activityId);
            for (int confSpoonId : confSpoonIds) { // 返回必须有内容
                spoonCntMap.put(confSpoonId, 0);
            }

            if (autoJoinRecordMap.containsKey(spoon.getUserId())) { // 合并所有的回访记录
                for (CookBoy2AutoJoinRecord record : autoJoinRecordMap.get(spoon.getUserId()).values()) {
                    if (record.getSpoonMap() != null) {
                        for (Map.Entry<Integer, Integer> kv : record.getSpoonMap().entrySet()) {
                            spoonCntMap.merge(kv.getKey(), kv.getValue(), Integer::sum);
                        }
                    }
                }
            }

            for (Map.Entry<Integer, Integer> kv : spoonCntMap.entrySet()) {
                CookBoyProto.CookBoy2SpoonTempMsg.Builder spoonTemp =
                        CookBoyProto.CookBoy2SpoonTempMsg.newBuilder();
                spoonTemp.setId(kv.getKey());
                spoonTemp.setCnt(kv.getValue());
                respMsg.addRecord(spoonTemp);
            }
            spoon.setIsReturn(1); // 这里先将返还标识置1，后续就不需要再同步过来了，实际汤勺数据以游戏服为准

            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_COOK_BOY2_DEAL_AUTO_JOIN_SPOON_REST,
                    respMsg);
            MessageHelper.sendPacket(spoon.getServerId(), spoon.getUserId(), pbMsg);
        }
    }
}
